import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.Vector;

import jpaul.DataStructs.Pair;
import jpaul.Graphs.*;

public class ReducedGraphBuilder {
	
	public Vector<Pair<String, String>> arc;
	public Vector<Integer> invoke;
	public HashMap<Pair<String, String>, Integer> edge;
	
	public ReducedGraphBuilder() {
		arc = new Vector<Pair<String, String>>();
		invoke = new Vector<Integer>();
		edge = new HashMap<Pair<String, String>, Integer>();
	}
	
	@SuppressWarnings("unchecked")
	public static void main(String args[]) {
		
		//Vector<Pair<String, String>> arc = new Vector<Pair<String, String>>();
		//Vector<Integer> invoke = new Vector<Integer>();
		
		ReducedGraphBuilder rgb = new ReducedGraphBuilder();
		
		try {
			BufferedReader input = new BufferedReader(new FileReader("edge.tuples"));
			String line = null;
			try {
				input.readLine();
				while ((line = input.readLine()) != null) {
					StringTokenizer st = new StringTokenizer(line);
					rgb.arc.add(new Pair(st.nextToken(), st.nextToken()));
					rgb.invoke.add(new Integer(st.nextToken()));
				}
				for (int i = 0; i < rgb.arc.size(); i++) {
					rgb.edge.put(rgb.arc.get(i), rgb.invoke.get(i));
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	// get rid off the header line
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ArcBasedDiGraph<String> graph = new ArcBasedDiGraph<String>(rgb.arc);
		
		HashMap<SCComponent<String>, Integer> context_map = new HashMap<SCComponent<String>, Integer>();
		
		// iterate over the list of strongly connected components
        // in incremental topological order
		
		int e;
		int c;
		/*
        for (SCComponent<String> scc : graph.getComponentDiGraph().decrOrder()) {
        	System.out.println("SCC vertices: " + scc.vertices());
            // potentially, do something more interesting with "scc" :)
        	context_map.put(scc, 1);
        	c = 0;
        	// For each incoming edge
        	if (scc.prev().size() > 0) {
        		for (SCComponent<String> pre_scc: scc.prev()) {
        			for (String v1: pre_scc.vertices()) {
        				for (String v2: scc.vertices()) {
                			System.out.println("vertex1: " + v1 + " vertex2: " + v2);
                			e = rgb.edge.get(new Pair(v1, v2));
                			//System.out.println("edge: " + rgb.edge.get(new Pair(v1, v2)));
                			c = context_map.get(pre_scc)*scc.size();
                			context_map.put(scc, c);
                			System.out.println("context size: " + c);
                			for (int i = 1; i <= context_map.get(scc); i++) {
                				System.out.println(i + " " + e + " " + "i+k" + " " + v2);
                			}	
                		}
        			}
        		}
        	}
        }
        */
		
		FileWriter IEc;
		try {
			IEc = new FileWriter("IEc.tuples");
			BufferedWriter out = new BufferedWriter(IEc);
			out.write("# C0:63 I0:32 C1:63 M0:32 \n");
			
			int k = 0;
			
			for (SCComponent<String> scc : graph.getComponentDiGraph().decrOrder()) {
				System.out.println("SCC vertices: " + scc.vertices());
				if(scc.prev().isEmpty()) {		// is root
					context_map.put(scc, 1);
				} /*else {
					context_map.put(scc, context_map.get(scc.prev().iterator().next())*scc.size());
				}*/
				// For each incoming edge
				c = 0;
				//k = context_map.get(scc);
				System.out.println("k: "+k);
				if (scc.prev().size() > 0) {
					for (String v2: scc.vertices()) {
						for (SCComponent<String> prev: scc.prev()) {
							context_map.put(scc, context_map.get(prev)*scc.size());
							k = context_map.get(scc);
							for (String v1 : prev.vertices()) {
								Pair p = new Pair(v1, v2);
								if (rgb.edge.containsKey(p)) {
									e = rgb.edge.get(p);
									for(int i=1; i<=k; i++){
										out.write(i + " " + e + " " + (i+c) + " " + v2 + "\n");
										System.out.println(i + " " + e + " " + (i+c) + " " + v2);
									}
									if(scc.size() == 1) {
										c = c+k;
										System.out.println("c: " + c);
										context_map.put(scc, c);
									}
								}
							}
						}
					}
				}
			}
			out.close();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
}
